home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
098
/
fft12.arc
/
FFT12.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-04-26
|
8KB
|
283 lines
program fft;
{$i typedef.sys}
{$i graphix.sys}
{$i kernel.sys}
{$i axis.hgh}
{$i polygon.hgh}
type
cmpl = record
re,im :real
end;
bigstr = string[12];
range = array[1..256] of cmpl;
var
filename,nstr,fileout :bigstr;
filnam,fiout :string[8];
xform :string[25];
inverse,output :char;
npoints,invt,d :integer;
rd :range;
procedure FindWorld(i:integer;
A:PlotArray;
NPoints:integer);
var XMax,YMax,XMin,YMin:real;
j:integer;
begin
NPoints:=abs(NPoints);
if NPoints>=2 then
if i in [1..MaxWorldsGlb] then
begin
XMax:=A[1,1];
YMax:=A[1,2];
XMin:=XMax;
YMin:=YMax;
for j:=2 to NPoints do
begin
if A[j,1]>XMax then XMax:=A[j,1]
else if A[j,1]<XMin then XMin:=A[j,1];
if A[j,2]>YMax then YMax:=A[j,2]
else if A[j,2]<YMin then YMin:=A[j,2];
end;
if (ymax=ymin) and (ymax=0) then begin
ymax:=1;
ymin:=0
end
else ymin:=0;
DefineWorld(i,XMin,YMin,XMax,YMax);
SelectWorld(i);
end
else error(7,2)
else error(7,4);
end;
procedure readdata(filename:bigstr;var d :range;var a:integer);
{range and bigstr are set up in the TYPE identifier
range = array[1..?] of real
bigstr = string[12]
a returns the transform length or file size}
type
data =
record
w,z :real;
end;
var
index :integer;
xy :array[1..256] of data;
datafile :file of data;
begin
assign(datafile,filename);
reset(datafile);
a:=filesize(datafile);
for index:=1 to a do begin
read(datafile,xy[index]);
with d[index] do begin
re:=xy[index].w;
im:=xy[index].z;
end;
end;
close(datafile);
end;
procedure writedata(filename:bigstr;var d:range;var a:integer);
type
data =
record
w,z :real;
end;
var
index :integer;
xy :array[1..256] of data;
datafile :file of data;
begin
assign(datafile,filename);
rewrite(datafile);
for index:=1 to a do begin
with xy[index] do begin
w:=d[index].re;
z:=d[index].im;
end;
write(datafile,xy[index]);
end;
close(datafile);
end;
PROCEDURE PLOT(inv,NOPTS :INTEGER; XK :RANGE);
VAR
HRZ:INTEGER;
b,a:PlotArray;
key:char;
titleRE,titleIM:string[40];
BEGIN
if inv=1 then begin
titlere:='Direct Transform --- Amplitude Response';
titleim:='Direct Transform --- Phase Response';
FOR HRZ:=1 TO NOPTS DO
BEGIN
a[HRZ,1]:=hrz-1;
b[HRZ,1]:=hrz-1;
a[HRZ,2]:=sqrt(sqr(XK[HRZ].RE)+sqr(xk[hrz].im));
b[HRZ,2]:=arctan(XK[HRZ].IM/xk[hrz].re);
END;
end
else begin
titlere:='Inverse Transform --- Real Part';
titleim:='Inverse Transform --- Imaginary Part';
FOR HRZ:=1 TO NOPTS DO
BEGIN
a[HRZ,1]:=hrz-1;
b[HRZ,1]:=hrz-1;
a[HRZ,2]:=xk[hrz].re;
b[HRZ,2]:=xk[hrz].im;
END;
end;
initgraphic;
CLEARSCREEN;
definewindow(1,0,0,xmaxglb,ymaxglb-20);
definewindow(2,0,0,xmaxglb,ymaxglb-20);
defineworld(2,b[1,1],-(pi/2),b[nopts,1],(pi/2));
DEFINEHEADER(1,titlere);
defineheader(2,titleim);
selectwindow(1);
setheaderon;
findworld(1,a,nopts); {automatically executes defineworld}
selectwindow(1);
drawborder;
drawaxis(7,5,0,0,0,0,0,0,false);
drawpolygon(a,1,nopts,0,2,0);
GOTOXY(1,25);
WRITELN('Press any key to continue...');
repeat until keypressed;
clearscreen;
selectworld(2);
selectwindow(2);
drawborder;
drawaxis(7,5,0,0,0,0,0,0,false);
drawpolygon(b,1,nopts,0,2,0);
repeat
GOTOXY(1,25);
WRITE('Press C to continue...');
read(kbd,key);
until key in ['c','C'];
leavegraphic;
end;
procedure fft(inv,n:integer;var ft:range);
{range is set up in the TYPE identifier and is = array[1..?] of real
inv = 1 if direct transform and =-1 for inverse
n = transform length power of 2}
var
le,ip,m,i,l,nm1,j,t,le1 :integer;
ur,ui,tr,ti,tmpr,tmpi,nv2,k :real;
begin
m:=round(ln(n)/ln(2));
if abs(m-int(m))=0 then begin
nv2:=n/2;
nm1:=n-1;
j:=1;
for i:=1 to nm1 do begin
if i<j then begin
tmpr:=ft[j].re;tmpi:=ft[j].im;
ft[j].re:=ft[i].re;ft[j].im:=ft[i].im;
ft[i].re:=tmpr;ft[i].im:=tmpi;
end;
k:=nv2;
while k<j do begin
j:=round(j-k);
k:=k/2;
end;
j:=round(j+k);
end;
for l:=1 to m do begin
le:=1;
for t:=1 to l do
le:=le*2;
le1:=round(le/2);
ur:=1;ui:=0;
for j:=1 to le1 do begin
i:=j;
while i<=n do begin
ip:=i+le1;
tr:=ft[ip].re*ur-ft[ip].im*ui;ti:=ft[ip].im*ur+ft[ip].re*ui;
ft[ip].re:=ft[i].re-tr;ft[ip].im:=ft[i].im-ti;
ft[i].re:=ft[i].re+tr;ft[i].im:=ft[i].im+ti;
i:=i+le;
end;
ur:=cos(pi*j/le1);ui:=-inv*sin(pi*j/le1);
end;
end;
if inv=-1 then begin
for i:=1 to n do begin
ft[i].re:=ft[i].re/n;
ft[i].im:=ft[i].im/n;
end;
end;
end;
end;
begin
clrscr;
gotoxy(29,1);writeln('Fast Fourier Transform');
gotoxy(39,3);writeln('by');
gotoxy(31,4);writeln('Michael F. Griffin');
writeln;writeln;writeln;
gotoxy(19,6);writeln('*----------------------------------------*');
gotoxy(8,8);writeln('- All file names are assumed to have .DAT as the extension.');
gotoxy(8,9);writeln('- Output goes to either a file or a printer.');
writeln;writeln;
write('Enter data file name w/o extension : ');
readln(filnam);
filename:=filnam+'.dat';
writeln('Input File name ==> : ',filename);
write('Do you want a direct transform <Y/N>?');
read(kbd,inverse);writeln;
if (inverse='Y') or (inverse='y') then begin
xform:='Direct Fourier Transform';
invt:=1
end
else begin
xform:='Inverse Fourier Transform';
invt:=-1
end;
write('Do you want the output to a file <Y/N>?');
read(kbd,output);writeln;
if (output='Y') or (output='y') then begin
write('Enter output data file name w/o extension : ');
readln(fiout);
fileout:=fiout+'.dat';
writeln('Output File name ==> : ',fileout);
end;
readdata(filename,rd,npoints);
fft(invt,npoints,rd);
plot(invt,npoints,rd);
if (output='Y') or (output='y') then
writedata(fileout,rd,npoints)
else begin
writeln(lst,xform);writeln(lst);
str(npoints,nstr);
for d:=1 to npoints do
writeln(lst,'(',d:length(nstr),')',rd[d].re,rd[d].im)
end;
end.